package reports;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import model.entity.Item;
import model.entity.Product;
import model.entity.container.ProductContainer;
import model.entity.container.ProductGroup;
import model.entity.container.StorageUnit;
import model.management.ItemManager;
import model.management.ProductGroupManager;
import model.management.ProductManager;
import model.management.StorageUnitManager;
import reports.builders.IBuilder;
import reports.display.ReportTable;
import reports.display.ReportTableRow;
import reports.visitor.IVisitor;

public class NMonthSupplyReport extends Report
{
  private static final String TITLE = " Month Supply Report";

  private static final String getTitle(int months)
  {
    return months + TITLE;
  }

  private IVisitor              visitor;
  private int                   months;
  private Set<Product>          products             = new HashSet<Product>();
  private Set<ProductGroup>     productGroups        = new HashSet<ProductGroup>();
  private ReportTable           productsTable;
  private ReportTable           productGroupsTable;
  private static final String[] PRODUCTSCOLUMNS      = new String[]
                                                     {
      "Description       ",
      "Barcode           ",
      "3-Month Supply    ",
      "current Supply    "
                                                     };
  private static final String[] PRODUCTSGROUPCOLUMNS = new String[]
                                                     {
      "ProductGroup      ",
      "Storage Unit      ",
      "3-Month Supply    ",
      "current Supply    "
                                                     };

  public NMonthSupplyReport(int months)
  {
    super(getTitle(months));

    productsTable = new ReportTable(null, PRODUCTSCOLUMNS);
    productGroupsTable = new ReportTable(null, PRODUCTSGROUPCOLUMNS);

    this.months = months;

    visitor = new NMonthSupplyReportVisitor();
  }

  @Override
  public void buildReport(IBuilder<?> builder)
  {
    builder.addTitle(getTitle());
    builder.addSubTitle("Products");
    builder.startTable(productsTable.getColumnCount());
    if (productsTable.getRowCount() != 0)
    {
      builder.addTableHeader(productsTable.getColumnTitles());
      Iterator<ReportTableRow> productsItr = productsTable.getRows();
      while (productsItr.hasNext())
        builder.addRow(productsItr.next().getCells());
    }
    builder.endTable();

    builder.addSubTitle("Product Groups");
    builder.startTable(productGroupsTable.getColumnCount());
    if (productGroupsTable.getRowCount() != 0)
    {
      builder.addTableHeader(productGroupsTable.getColumnTitles());
      Iterator<ReportTableRow> productGroupItr = productGroupsTable.getRows();
      while (productGroupItr.hasNext())
        builder.addRow(productGroupItr.next().getCells());
    }
    builder.endTable();
  }

  @Override
  protected void visitData() throws Exception
  {
    ProductGroupManager.getInstance().preOrderAccept(visitor);
    ProductManager.getInstance().preOrderAccept(visitor);
  }

  @Override
  protected void interpretData() throws Exception
  {
    for (Product product : products)
    {
      int currentSupply = 0;
      List<ProductContainer> pcs = product.getContainers();
      for (int i = 0; i < product.getContainers().size(); i++)
      {
        currentSupply += ItemManager.getItemData(pcs.get(i), product).size();
      }
      if (currentSupply < (product.getSize().getAmount() * months))
      {
        ReportTableRow row = productsTable.createRow();
        row.setCell(0, product.getDescription());
        row.setCell(1, product.getBarcode().getCode());
        row.setCell(2, product.getSize());
        row.setCell(3, currentSupply + " " + product.getSize().getUnit());
        productsTable.addRow(row);
      }
    }

    for (ProductGroup productGroup : productGroups)
    {
      int currentSupply = 0;
      Iterator<Product> products = productGroup.getProducts();

      while (products.hasNext())
      {
        Product product = products.next();
        Iterator<Item> items = productGroup.getItems(product);
        while (items.hasNext())
        {
          currentSupply += product.getSize().getAmount();
          items.next();
        }
      }

      if (currentSupply < (productGroup.getThreeMonthSupply().getAmount() * (months / 3f)))
      {
        ReportTableRow row = productGroupsTable.createRow();
        row.setCell(0, productGroup.getName());
        row.setCell(1, StorageUnitManager.getStorageUnit(productGroup).getName());
        row.setCell(2, productGroup.getThreeMonthSupply());
        row.setCell(3, currentSupply + " " + productGroup.getThreeMonthSupply().getUnit());
        productGroupsTable.addRow(row);
      }
    }
  }

  private class NMonthSupplyReportVisitor implements IVisitor
  {
    @Override
    public void visit(ProductGroup productgroup)
    {
      productGroups.add(productgroup);
    }

    @Override
    public void visit(StorageUnit storageunit)
    {
      // do nothing
    }

    @Override
    public void visit(Item item)
    {
      // do nothing
    }

    @Override
    public void visit(Product product)
    {
      products.add(product);
    }
  }
}
